package org.lionel.task;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;


public class JobInfo<R> {

    /**
     * 工作名，用以区分框架中唯一的工作
     */
    private final String jobName;
    /**
     * 工作中任务的长度，即一个工作多少个任务
     */
    private final int jobLength;
    /**
     * 处理工作中任务的处理器
     */
    private final ITaskProcesser<?, ?> taskProcesser;
    /**
     * 任务的成功次数
     */
    private AtomicInteger successCount;
    /**
     * 工作中任务目前已经处理的次数
     */
    private AtomicInteger taskProcessCount;
    /**
     * 存放每个任务的处理结果，供查询用
     */
    private LinkedBlockingDeque<TaskResult<R>> taskDetailQueues;
    /**
     * 保留工作结果信息供查询的时长
     */
    private final long expireTime;
    /**
     * checkJobProcesser，用于添加处理的结果到延时队列
     */
    private CheckJobProcesser checkJobProcesser = CheckJobProcesser.getInstance();

    public JobInfo(String jobName, int jobLength,
                   ITaskProcesser<?, ?> taskProcesser,
                   long expireTime) {
        this.jobName = jobName;
        this.jobLength = jobLength;
        this.taskProcesser = taskProcesser;
        this.successCount = new AtomicInteger(0);
        this.taskProcessCount = new AtomicInteger(0);
        this.taskDetailQueues = new LinkedBlockingDeque<>(jobLength);
        this.expireTime = expireTime;
    }

    public String getJobName() {
        return jobName;
    }

    public int getJobLength() {
        return jobLength;
    }

    public long getExpireTime() {
        return expireTime;
    }

    public ITaskProcesser<?, ?> getTaskProcesser() {
        return taskProcesser;
    }

    public AtomicInteger getTaskProcessCount() {
        return taskProcessCount;
    }

    public AtomicInteger getSuccessCount() {
        return successCount;
    }

    /**
     * 失败次数
     */
    public long getFailureCount() {
        return taskProcessCount.get() - successCount.get();
    }

    /**
     * 工作的整体进度信息
     */
    public String getTotalProcess() {
        return "Success[ " + successCount.get() + " ] / Current[ " + taskProcessCount.get() + " ] Total[ " + jobLength + " ]";
    }

    /**
     * 提供工作中每个任务的处理结果
     */
    public List<TaskResult<R>> getTaskDetail() {
        List<TaskResult<R>> taskResultList = new LinkedList<>();
        TaskResult<R> taskResult;
        while ((taskResult = taskDetailQueues.pollFirst()) != null) {
            taskResultList.add(taskResult);
        }
        return taskResultList;
    }

    /**
     * 个任务处理完成后，记录任务的处理结果，因为从业务应用的角度来说，
     * 对查询任务进度数据的一致性要不高
     * 我们保证最终一致性即可，无需对整个方法加锁
     */
    public void addTaskResult(TaskResult<R> taskResult){
        if(TaskResultType.SUCCESS.equals(taskResult.getTaskResultType())){
            successCount.incrementAndGet();
        }
        taskProcessCount.incrementAndGet();
        taskDetailQueues.addLast(taskResult);
        if(taskProcessCount.get() == jobLength){
            checkJobProcesser.putJob(expireTime, jobName);
        }
    }
}